/*******************************************************/
//Project: 光剑/十字光剑通用固件
//Designed: 大玉菌 
//Data: 2024.7
/*******************************************************/

#include <Arduino.h>
#include "Audio.h"
#include "SPI.h"
#include "SD.h"
#include "FS.h"
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
//#include <pgmspace.h>   // PROGMEM library  把数据存储到flash里面

#include <Adafruit_NeoPixel.h>
#include "EEPROM.h"
#include "esp_system.h"
#include <MadgwickAHRS.h>

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN    2
#define LED_PIN1    14
#define LED_PIN2    15

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT    156        //主剑刃灯数
#define LED_COUNT1    18        //十字光剑侧剑刃灯数
#define LED_COUNT2    18        //十字光剑侧剑刃灯数

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip1(LED_COUNT1, LED_PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(LED_COUNT2, LED_PIN2, NEO_GRB + NEO_KHZ800);


// Digital I/O used
#define SD_CS         4
#define SPI_MOSI      5
#define SPI_MISO      7
#define SPI_SCK       6
#define I2S_DOUT      8
#define I2S_BCLK      10
#define I2S_LRC       9

#define BTN           1
#define BTN_LED       13
#define VOLT_PIN      3

#define MAXBRIGHT     200

#define I2C_MASTER_SCL_IO 11      /*!< gpio number for I2C master clock */
#define I2C_MASTER_SDA_IO 12      /*!< gpio number for I2C master data  */

#define DEBUG  1
#define HUM_TIMEOUT    30228     //hum1.wav 刷新时间

#define BTN_TIMEOUT 1000     // 按键刷新时间

#define SWING_TIMEOUT 1000   // 摆动刷新时间
#define SWING_L_THR 180      // swing 角度阈值
#define SWING_THR 360        // fast swing 角度阈值
#define STRIKE_THR 80        // hit 加速度阈值    
#define STRIKE_S_THR 320     // hard hit 加速度阈值 
#define FLASH_DELAY 15       // 敲击延时
#define OPEN_THR   160       // 开机阈值

#define PULSE_ALLOW 1       //脉冲使能
#define PULSE_AMPL 10       //脉冲幅度      
#define PULSE_DELAY 30      //脉冲间隔

#define R1 100000            //分压电阻 
#define R2 100000            //分压电阻
#define BATTERY_SAFE 0       //电池监测(1 - allow, 0 - disallow) 

#define GESTURE_ALLOW   1    //手势开机使能(1 - allow,0 - disallow)

Audio audio;                 //音频         

MPU6050 accelgyro;           //mpu6050
int16_t ax, ay, az;
int16_t gx, gy, gz;
unsigned long ACC, GYR;
int gyroX, gyroY, gyroZ, accelX, accelY, accelZ;
int16_t Lastgx,Lastgy,Lastgz,Lastax,Lastay,Lastaz;
int Diffgx,Diffgy,Diffgz,Diffax,Diffay,Diffaz;

float k = 0.2;
unsigned long humTimer = -HUM_TIMEOUT, mpuTimer, gestureTimer;    //上次时间计数
unsigned long btn_timer, PULSE_timer, swing_timer, swing_timeout,strike_timeout, battery_timer,FLASH_timer,hit_timer;   //btn_timer：按键更新时间 PULSE_timer：脉冲更新时间 swing_timer：摆动更新时间 swing_timeout：摆动更新 battery_timer：电池更新时间 FLASH_timer 灯带更新时间 hit_timer 敲击更新时间 
boolean ls_chg_state, ls_state;                               // ls_chg_state:按键切换状态   ls_state:开关状态 
boolean bzzz_flag , btnState, btn_flag, hold_flag;            //bzzz_flag:喇叭状态  btnState:按键状态  btn_flag：按键标志 hold_flag：按住标志
boolean lighton_flag, lightoff_flag,hit_flag;                 //lighton_flag: 灯带开机标志  lightoff_flag：灯带关机标志   hit_flag：敲击标志
byte btn_counter,light_counter,light_counter1,light_counter2;                //btn_counter ：按键计数器  light_counter：灯带更新计数器 light_counter1:十字灯带计数器
byte nowNumber, nowColor;                                     //nowNumber:当前音频 nowColor:当前颜色   
byte red, green, blue, redOffset, greenOffset, blueOffset;    //RGB
boolean eeprom_flag, swing_flag, swing_allow, strike_flag;    //eeprom_flag:e2p存储标志位 swing_flag：晃动标志位 swing_allow：未使用 strike_flag：敲击标志位 
float voltage;                                                //电压
int PULSEOffset;                                              //脉冲偏置
char BUFFER[20];

#define IMU_CAL_COUNTER  (1<<3)
uint32_t ges_counter = 0;                                     //手势计数器
float rolls[IMU_CAL_COUNTER] = {0};                           //翻滚角缓存                      
float pitchs[IMU_CAL_COUNTER] = {0};                          //俯仰角缓存          
Madgwick filter;

// --------------------------------- SOUNDS ----------------------------------
//in 
const char in_s1[]  = "in1.wav";
const char in_s2[]  = "in2.wav";

const char* const in_cache[]  = {
  in_s1, in_s2
};

int in_time[2] = { 1586, 786};

//out
const char out_s1[]  = "out1.wav";
const char out_s2[]  = "out2.wav";

const char* const out_cache[]  = {
  out_s1, out_s2
};

int out_time[2] = { 2145, 1770};

//hit
const char clsh_s1[]  = "clsh1.wav";
const char clsh_s2[]  = "clsh2.wav";
const char clsh_s3[]  = "clsh3.wav";
const char clsh_s4[]  = "clsh4.wav";
const char clsh_s5[]  = "clsh5.wav";
const char clsh_s6[]  = "clsh6.wav";
const char clsh_s7[]  = "clsh7.wav";
const char clsh_s8[]  = "clsh8.wav";
const char clsh_s9[]  = "clsh9.wav";
const char clsh_s10[]  = "clsh10.wav";


const char* const clsh_cache[]  = {
  clsh_s1, clsh_s2, clsh_s3, clsh_s4, clsh_s5, clsh_s6, clsh_s7, clsh_s8,clsh_s9,clsh_s10,
};
int clsh_time[10] = {765,610,644,477,682,547,725,734,878,584};

//swing
const char swng1[]  = "swng1.wav";
const char swng2[]  = "swng2.wav";
const char swng3[]  = "swng3.wav";
const char swng4[]  = "swng4.wav";
const char swng5[]  = "swng5.wav";
const char swng6[]  = "swng6.wav";  
const char swng7[]  = "swng7.wav";
const char swng8[]  = "swng8.wav";
const char swng9[]  = "swng9.wav";
const char swng10[]  = "swng10.wav";
const char swng11[]  = "swng11.wav";
const char swng12[]  = "swng12.wav";
const char swng13[]  = "swng13.wav";
const char swng14[]  = "swng14.wav";
const char swng15[]  = "swng15.wav";

const char* const swngs[]   = {
  swng1, swng2, swng3, swng4, swng5,swng6, swng7, swng8, swng9, swng10,
  swng11, swng12, swng13, swng14, swng15
};
int swng_time[15] = {591,767,685,893,900,1273,626,546,400,901,521,767,403,893,434};


void getMpu6050();
void on_off_sound();
void setAll(byte red, byte green, byte blue);
void setColor(byte color);
void randomPULSE();
void batteryTick();
byte voltage_measure();
void btnTick();
void create_lighton_action();
void create_lightoff_action();
void create_hit_action();
void strikeTick();
void swingTick();
void gestureTick();
void lightTick();

void setup() {
  delay(1000);

  // ---- 按键初始化 ----
  pinMode(BTN, INPUT_PULLUP);
  pinMode(BTN_LED, OUTPUT);
  pinMode(VOLT_PIN,INPUT);
  digitalWrite(BTN_LED, 1);

  Serial.begin(115200);

  analogReadResolution(12);

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.setBrightness(100); // Set BRIGHTNESS to about 1/5 (max = 255)
  strip.show();            // Turn OFF all pixels ASAP

  strip1.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip1.setBrightness(100); // Set BRIGHTNESS to about 1/5 (max = 255)
  strip1.show();            // Turn OFF all pixels ASAP

  strip2.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip2.setBrightness(100); // Set BRIGHTNESS to about 1/5 (max = 255)
  strip2.show();            // T

  delay(200);
  Wire.begin(I2C_MASTER_SDA_IO,I2C_MASTER_SCL_IO);
  // IMU 6050 initialization
  accelgyro.initialize();
  accelgyro.setFullScaleAccelRange(MPU6050_ACCEL_FS_16);
  accelgyro.setFullScaleGyroRange(MPU6050_GYRO_FS_250);   
  if (DEBUG) {
    if (accelgyro.testConnection()) Serial.println(F("MPU6050 OK"));
    else Serial.println(F("MPU6050 fail"));
  }
  filter.begin(1000000/50);

  pinMode(SD_CS, OUTPUT);      digitalWrite(SD_CS, HIGH);
  SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
  SPI.setFrequency(1000000);

  SD.begin(SD_CS);

  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  audio.setVolume(20); // 0...21
  // audio.setBufsize(0, 3 * 1024 * 1024);

  if(!EEPROM.begin(10))
  {
    if (DEBUG) Serial.println(F("EEPROM init fail"));
    nowColor = 0;
  }
  else
  {
    if (DEBUG) Serial.println(F("EEPROM init OK"));
    if ((EEPROM.read(0) >= 0) && (EEPROM.read(0) <= 5)) {  // check first start
      nowColor = EEPROM.read(0);   // remember color
    } else {                       // first start
      EEPROM.write(0, 0);          // set default
      EEPROM.commit();
      nowColor = 0;                // set default
    }
  }
  setColor(nowColor);
  strip.setBrightness(MAXBRIGHT);
  strip1.setBrightness(MAXBRIGHT);
  strip2.setBrightness(MAXBRIGHT);
  if (DEBUG) Serial.println("lightsaber start.wav");
  audio.connecttoFS(SD,"font.wav");
  delay(1000);
}

void loop() {
    audio.loop();
    getMpu6050();
    btnTick();
    on_off_sound();
    randomPULSE();
    strikeTick();
    swingTick();
    gestureTick();
    lightTick();
    batteryTick();
}


//获取陀螺仪数据
void getMpu6050() {
  if (ls_state) 
  {                                               // if saber is on
    if (millis() - mpuTimer > 200) {                            
      accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);       

      // find absolute and divide on 100
      gyroX = abs(gx / 100);
      gyroY = abs(gy / 100);
      gyroZ = abs(gz / 100);
      accelX = abs(ax / 100);
      accelY = abs(ay / 100);
      accelZ = abs(az / 100);

      // vector sum
      ACC = sq((long)accelX) + sq((long)accelY) + sq((long)accelZ);
      ACC = sqrt(ACC);
      GYR = sq((long)gyroX) + sq((long)gyroY) + sq((long)gyroZ);
      GYR = sqrt((long)GYR/2);
      mpuTimer = millis();
    }
  }
}

//手势状态
void gestureTick()
{ 
    if(GESTURE_ALLOW == 1)
    {
      static int16_t count_open = 0;
    //  static int16_t count_change = 0; 
      float roll_min,roll_max;
      float pitch_min,pitch_max; 

      if(millis() - gestureTimer > 50)
      {
          gestureTimer = millis();
          accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); 

          float accX = (float)ax/2048.0;     //(32768.0/16)
          float accY = (float)ay/2048.0;
          float accZ = (float)az/2048.0;

          float gyroX = (float)gx/131.0;     //32768.0/250
          float gyroY = (float)gy/131.0;
          float gyroZ = (float)gz/131.0;

          // float roll,pitch,yaw;
          // filter.updateIMU(gyroX, gyroY, gyroZ, accX, accY, accZ);
          // // print the heading, pitch and roll
          // roll = filter.getRoll();
          // pitch = filter.getPitch();
          // yaw = filter.getYaw();

          rolls[ges_counter & (IMU_CAL_COUNTER-1)] = atan2(accY,accZ)*57.2974;
          pitchs[ges_counter & (IMU_CAL_COUNTER-1)] = atan2(-accX,sqrt(accY * accY + accZ * accZ))*57.2974;

          roll_min = pitch_min = 10000;
          roll_max = pitch_max = -10000;
          for(int i=0;i<IMU_CAL_COUNTER;i++)
          {
              roll_min =  rolls[i] < roll_min ? rolls[i] : roll_min;
              roll_max = rolls[i] > roll_max ? rolls[i] : roll_max;
              pitch_min =  pitchs[i] < pitch_min ? pitchs[i] : pitch_min;
              pitch_max = pitchs[i] > pitch_max ? pitchs[i] : pitch_max; 
          }

          if(pitch_max - pitch_min > OPEN_THR && count_open == 0)
          {
            ls_chg_state = 1;
            count_open = 40;
            // Serial.println("Roll P-P = ");
            // Serial.println(roll_max - roll_min);
            // Serial.println("Pitch P-P = ");
            // Serial.println(pitch_max - pitch_min);
          }

          ges_counter ++ ;

          if(count_open > 0) count_open--;
          // if(count_change > 0) count_change--;
      }   
    } 
    
}

//按键状态函数
void btnTick() {
  btnState = !digitalRead(BTN);                        //获取按键状态
  if (btnState && !btn_flag)                           //按下                                           
  {                                  
    if (DEBUG) Serial.println(F("BTN PRESS"));
    btn_flag = 1;                                      //按下的状态
    btn_counter++;                                      
    btn_timer = millis();                              //按下的时间
  }
  if (!btnState && btn_flag) {                         //按键释放
    btn_flag = 0;
    hold_flag = 0;                                                                 
  }
  //长按 开关光剑
  if (btn_flag && btnState && (millis() - btn_timer > BTN_TIMEOUT) && !hold_flag) 
  {
    ls_chg_state = 1;                     // flag to change saber state (on/off)
    hold_flag = 1;                        
  }
  //连按 触发
  if ((millis() - btn_timer > BTN_TIMEOUT) && (btn_counter != 0)) {
    if (ls_state) {
       if (DEBUG) Serial.println("Change color");
      if (btn_counter >= 3) {               // 3 press count
        nowColor++;                         // change color
        if (nowColor >= 5) nowColor = 0;
        setColor(nowColor);
        eeprom_flag = 1;
      }
    }
    btn_counter = 0;
  }
}

//声音开关 切换完执行一次
void on_off_sound() {
if (ls_chg_state) {                // if change flag
    if (!ls_state)                   // if Saber is turned off   
    {
      if (voltage_measure() > 10 || !BATTERY_SAFE) 
      {
        if (DEBUG) Serial.println(F("SABER ON"));
         nowNumber = esp_random() % 2 ;
        audio.connecttoFS(SD, out_cache[nowNumber]);                                                                              
        humTimer = millis() - HUM_TIMEOUT + out_time[0];    //-9000是因为HUM.wav是9000ms                               
        create_lighton_action();
        ls_state = 1;             // remember that turned on
        bzzz_flag = 1;
      } 
      else 
      {
        if (DEBUG) Serial.println(F("LOW VOLTAGE!"));
        for (int i = 0; i < 5; i++) {
          digitalWrite(BTN_LED, 0);
          delay(400);
          digitalWrite(BTN_LED, 1);
          delay(400);
        }
      }
    } else {                         // turned on
      bzzz_flag = 0; 
      nowNumber = esp_random() % 2 ;
      audio.connecttoFS(SD, in_cache[nowNumber]);  
      humTimer = millis() - HUM_TIMEOUT + in_time[1];    //-9000是因为HUM.wav是9000ms       
      create_lightoff_action();           
      if (DEBUG) Serial.println(F("SABER OFF"));
      ls_state = 0;               
      if (eeprom_flag) 
      {
        eeprom_flag = 0;
        EEPROM.write(0, nowColor);   // write color in EEPROM
        EEPROM.commit();
      }
    }
    ls_chg_state = 0;
  }

  //SD卡音频播放
  if ((millis() - humTimer) > HUM_TIMEOUT && bzzz_flag) {
    audio.connecttoFS(SD, "hum1.wav");                //
    humTimer = millis();
    swing_flag = 1;
    strike_flag = 0;
  }  
}

//敲击动作
void strikeTick() {

  if ((ACC > STRIKE_THR) && (ACC < STRIKE_S_THR)&&(millis() - strike_timeout > 500)&& ls_state && lighton_flag == 0 && lightoff_flag == 0) { 
    strike_timeout = millis();
    nowNumber = esp_random() % 10;
    audio.connecttoFS(SD, clsh_cache[nowNumber]);                                                                              
    humTimer = millis() - HUM_TIMEOUT + clsh_time[nowNumber];                                                                   //敲击标志位
    create_hit_action();
    strike_flag = 1;                                //播放完以后  strike_flag归零
  }

}

//摆动动作  
void swingTick() {
  if (GYR > 120 && (millis() - swing_timeout > 200)&& ls_state && lighton_flag == 0 && lightoff_flag == 0)     //200ms更新一次
  {
    swing_timeout = millis();
    if (((millis() - swing_timer) > SWING_TIMEOUT) && swing_flag && !strike_flag) {
      if (GYR >= SWING_THR) {                             //swing               
        nowNumber = esp_random() % 15 ;
        nowNumber = (nowNumber/2)*2 + 1;         
        audio.connecttoFS(SD, swngs[nowNumber]);                
        humTimer = millis() - HUM_TIMEOUT + swng_time[nowNumber];
        swing_flag = 0;
        swing_timer = millis();
      }
      else if(GYR <= SWING_THR && GYR >  SWING_L_THR)
      {
        nowNumber = esp_random() % 15 ;
        nowNumber = (nowNumber/2)*2;         
        audio.connecttoFS(SD, swngs[nowNumber]);                
        humTimer = millis() - HUM_TIMEOUT + swng_time[nowNumber];
        swing_flag = 0;
        swing_timer = millis();          
      }
    }
  }
}


 //随机脉冲
void randomPULSE() {
  //PULSE_ALLOW 使能脉冲 ls_state 按键打开
  if (PULSE_ALLOW && ls_state && (millis() - PULSE_timer > PULSE_DELAY) && lighton_flag == 0 && lightoff_flag == 0 && hit_flag == 0) {
    PULSE_timer = millis();
    PULSEOffset = PULSEOffset * k + map((esp_random()%1024),0,1024,-PULSE_AMPL,PULSE_AMPL) * (1 - k);     //一阶滤波
    if (nowColor == 0) PULSEOffset = constrain(PULSEOffset, -15, 5);
    redOffset = constrain(red + PULSEOffset, 0, 255);
    greenOffset = constrain(green + PULSEOffset, 0, 255);
    blueOffset = constrain(blue + PULSEOffset, 0, 255);
    setAll(redOffset, greenOffset, blueOffset);
  }
}

//灯带刷新
void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < LED_COUNT; i++ ) {
    strip.setPixelColor(i, red, green, blue);
  }
  strip.show();
    for (int i = 0; i < LED_COUNT1; i++ ) {
    strip1.setPixelColor(i, red, green, blue);
  }
  strip1.show();
    for (int i = 0; i < LED_COUNT2; i++ ) {
    strip2.setPixelColor(i, red, green, blue);
  }  
  strip2.show();
}
 //灯带开机动作
void create_lighton_action()
{
    lighton_flag = 1;
    light_counter = 0;
    light_counter1 = 0;
    light_counter2 = 0;
}
//灯带关机动作
void create_lightoff_action()
{
    lightoff_flag = 1;
    light_counter =  LED_COUNT / 2 - 1;
    light_counter1 = LED_COUNT1 / 2 - 1;
    light_counter2 = LED_COUNT2 / 2 - 1; 
}

//灯带敲击动作
void create_hit_action()
{
    setAll(255, 201, 0);        
    hit_timer = millis();
    hit_flag = 1;
}
 
//控制灯
void lightTick()
{  
   //ON
   if ((millis() - FLASH_timer > FLASH_DELAY) && lighton_flag )
   {     
      FLASH_timer = millis();
      strip.setPixelColor(light_counter, red, green, blue);
      strip.setPixelColor((LED_COUNT - 1 - light_counter), red, green, blue);
      strip.show();
      light_counter ++ ;
      if(light_counter >= (LED_COUNT / 2 - 1))
      {
        light_counter = 0;
        for(int i=0; i< LED_COUNT1;i++ )
          strip1.setPixelColor(i, red, green, blue);
        strip1.show();  
        for(int i=0; i< LED_COUNT2;i++ )
          strip2.setPixelColor(i, red, green, blue);
        strip2.show();
        lighton_flag = 0;
      }
   }
   //OFF
   if ((millis() - FLASH_timer > FLASH_DELAY) && lightoff_flag)
   {     
      FLASH_timer = millis();
      strip.setPixelColor(light_counter, 0, 0, 0);
      strip.setPixelColor((LED_COUNT - 1 - light_counter), 0, 0, 0);
      strip.show();
      if(light_counter == 0)
      {
        light_counter = 0;
        lightoff_flag = 0;
        for(int i=0; i< LED_COUNT1;i++ )
          strip1.setPixelColor(i, 0, 0, 0);
        strip1.show();  
        for(int i=0; i< LED_COUNT2;i++ )
          strip2.setPixelColor(i, 0, 0, 0);
        strip2.show();
      }
      else
        light_counter -- ; 
   }
   //HIT   
   if((millis() - hit_timer > FLASH_DELAY) && hit_flag && ls_state)
   {  
      hit_timer = millis();
      setAll(red, blue, green);    
      hit_flag = 0;     
   }
}


//配置颜色
void setColor(byte color) {
  switch (color) {
    // 0 - red, 1 - green, 2 - blue, 3 - pink, 4 - yellow, 5 - ice blue
    case 0:
      red = 255;
      green = 0;
      blue = 0;
      break;
    case 1:
      red = 0;
      green = 0;
      blue = 255;
      break;
    case 2:
      red = 0;
      green = 255;
      blue = 0;
      break;
    case 3:
      red = 255;
      green = 0;
      blue = 255;
      break;
    case 4:
      red = 255;
      green = 255;
      blue = 0;
      break;
    case 5:
      red = 0;
      green = 255;
      blue = 255;
      break;
  }
}

//电池检测
void batteryTick() {
  if (millis() - battery_timer > 30000 && ls_state && BATTERY_SAFE) {
    if (voltage_measure() < 15) {
      ls_chg_state = 1;
    }
    battery_timer = millis();
  }
}

//获取电池电量
byte voltage_measure() {
  voltage = 0;  
  for (int i = 0; i < 10; i++) {    
    voltage += (float)analogRead(VOLT_PIN) * 3.3 / 4095.0 ;
  }

  voltage = voltage / 10;          
  int volts = voltage * (R1 + R2)/R2  * 100;   
  if (volts > 387)
    return map(volts, 420, 387, 100, 77);
  else if ((volts <= 387) && (volts > 375) )
    return map(volts, 387, 375, 77, 54);
  else if ((volts <= 375) && (volts > 368) )
    return map(volts, 375, 368, 54, 31);
  else if ((volts <= 368) && (volts > 340) )
    return map(volts, 368, 340, 31, 8);
  else if (volts <= 340)
    return map(volts, 340, 260, 8, 0);
}

// optional
// void audio_info(const char *info){
//     Serial.print("info        "); Serial.println(info);
// }
// void audio_id3data(const char *info){  //id3 metadata
//     Serial.print("id3data     ");Serial.println(info);
// }
// void audio_eof_mp3(const char *info){  //end of file
//     Serial.print("eof_mp3     ");Serial.println(info);
// }
// void audio_showstation(const char *info){
//     Serial.print("station     ");Serial.println(info);
// }
// void audio_showstreamtitle(const char *info){
//     Serial.print("streamtitle ");Serial.println(info);
// }
// void audio_bitrate(const char *info){
//     Serial.print("bitrate     ");Serial.println(info);
// }
// void audio_commercial(const char *info){  //duration in sec
//     Serial.print("commercial  ");Serial.println(info);
// }
// void audio_icyurl(const char *info){  //homepage
//     Serial.print("icyurl      ");Serial.println(info);
// }
// void audio_lasthost(const char *info){  //stream URL played
//     Serial.print("lasthost    ");Serial.println(info);
// } 

